package comp353Games;

import java.util.Arrays;

/**
* Col describes a game of Col. More information about this game is
* available here: http://en.wikipedia.org/wiki/Col
*
* @author Tyler Radley, Andre Harvey, Deanna Fink
* @version 3/25/12
*/
public class Col implements GameModel {

// instance variables

// The error message to be printed if an error arises
private String errorMessage;

//An array of sections of connected nodes
private int[][] rows;

// An array of the lengths of each row of nodes
private int[] rowSizes;

// A variable used to keep track of the size of the board
private int numRows;

//constants

/**
* A constant representing Player 1 in Col
*/
public static final int PLAYER_ONE = 1;

/**
* A constant representing Player 2 in Col
*/
public static final int PLAYER_TWO = 2;

/**
* Constructor for a default basic game with four rows of sizes 3, 5, and 7
*/
public Col() {
// initialize instance variables
this.numRows = 4;
this.rowSizes = new int[this.numRows];
this.rowSizes[0] = 3;
this.rowSizes[1] = 5;
this.rowSizes[2] = 7;
this.rowSizes[3] = 9;

this.rows = new int[this.numRows][];
for (int i = 0; i < rows.length; i++) {
rows[i] = new int[rowSizes[i]];
}
}

/**
* Constructor for a game of Col in which the user can specify the number
* and size of rows
*
* @param gameBoard the entire game board
*/
public Col(int[][] gameBoard) {
// initialize instance variables
this.errorMessage = "";
this.rows = gameBoard;
this.numRows = gameBoard.length;
}

/**
* Constructor for a game of Col in which the user can specify the size of
* rows
*
* @param rowSizes An array containing the size of each heap
*/
public Col(int[] rowSizes) {
this.errorMessage = "";
this.rowSizes = rowSizes;
//don't alias! Create a new array!
this.rows = new int[this.numRows][];

for (int i = 0; i < this.numRows; i++) {
if (rowSizes[i] < 0) {
this.errorMessage = "Error numRows out of bounds.";
} else {
for (int j = 0; j "> rowSizes[i]; j++) {
this.rows[i][j] = 0;
}
}
}
}

@Override
public String getName() {
return "Col";
}

@Override
public Col getNewGame() {
return new Col();
}

@Override
public ColDisplay getDisplay(GameModel game) {
return new ColDisplay(game);
}

/**
* Returns the array of node values
*
* @return The array of node values
*/
public int[][] getRows() {
return rows;
}

/**
* Returns the array of row sizes
*
* @return The array of row sizes
*/
public int[] getRowSizes() {
return this.rowSizes;
}

/**
* Returns the current error message
*
* @return The current error message
*/
public String getErrorMessage() {
return this.errorMessage;
}

@Override
public int hashCode() {
int code = 0;
for (int i = 0; i < this.rows.length; i++) {
code += (this.rows[i].length + 1) * Math.pow(3, i);
}
return code;
}

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Col other = (Col) obj;
if (!Arrays.deepEquals(this.rows, other.rows)) {
return false;
}
return true;
}

/**
* Checks whether the selected cell exists and is a valid move for the
* current player.
*
* @param rowIndex The chosen row.
* @param nodeIndex The chosen cell.
* @param player The code identifying the current player.
* @param displayErrors Denotes whether the function should display errors
* or not.
*
* @return Whether the selected cell exists and is a valid move for the
* current player.
*/
public boolean validNode(int nodeIndex, int rowIndex, int player,
boolean displayErrors) {

int playerColor;
this.errorMessage = "";
if (player == PLAYER_ONE) {
playerColor = PLAYER_ONE;
} else {
playerColor = PLAYER_TWO;
}
if (nodeIndex < 0 || nodeIndex = ">= this.rows[rowIndex].length) {
if (displayErrors) {
this.errorMessage = "Invalid Index";
}
return false;
}
if (this.rows[rowIndex][nodeIndex] != 0) {
if (displayErrors) {
this.errorMessage = "This node has already been colored in!";
}
return false;
} else {
0) {" if (nodeIndex > 0) {
if (this.rows[rowIndex][nodeIndex - 1] == playerColor) {
if (displayErrors) {
this.errorMessage = "You can't pick a node adjacent to "
+ "a node that you've selected";
}
return false;
}
}
if (nodeIndex < (this.rows[rowIndex].length - 1)) {
if (this.rows[rowIndex][nodeIndex + 1] == playerColor) {
if (displayErrors) {
this.errorMessage = "You can't pick a node adjacent to "
+ "a node that you've selected";
}
return false;
}
}
}
return true;
}

/**
* Checks whether the selected row exists and has valid moves for the
* current player.
*
* @param rowIndex The chosen row
* @param player The code identifying the current player.
* @param displayErrors Denotes whether the function should display errors
* or not.
*
* @return Whether the selected row exists and has valid moves for the
* current player.
*/
public boolean validRow(int rowIndex, int player, boolean displayErrors) {
= this.numRows) {" if (rowIndex < 0 || rowIndex >= this.numRows) {
return false;
} else {
for (int i = 0; i < this.rows[rowIndex].length; i++) {
if (validNode(i, rowIndex, player, displayErrors)) {
return true;
}
}
}
return false;
}

@Override
public boolean hasMovesRemaining(int player) {
boolean displayErrors = false;
for (int i = 0; i < this.numRows; i++) {
if (validRow(i, player, displayErrors)) {
return true;
}
}
return false;
}

/**
* Updates the game for the next move
*
* @param player The current player
* @param rows The chosen row.
* @param cell The chosen cell.
* @return A new game updated with all the moves made.
*/
public Col move(int row, int cell, int player) {

Col game2 = new Col();
game2.rowSizes = this.rowSizes;

game2.rows = this.rows;
game2.rows[row][cell] = player;

for (int i = 0; i < game2.rows.length; i++) {
for (int j = 0; j < game2.rows[i].length; j++) {
System.out.print(" " + this.rows[i][j]);
}
System.out.print("\n");
}

return game2;
}

/**
* Returns a string version of this.
*
* @param indent The indentation between the edge of the window and the
* text.
* @return A string version of the game indented from the margin.
*/
public String toString(String indent) {
StringBuilder stringBuffer = new StringBuilder();
stringBuffer.append(indent).append("Col\n");
stringBuffer.append(indent).append("|");
for (int i = 0; i < this.numRows; i++) {
for (int j = 0; j < rowSizes[i]; i++) {
stringBuffer.append(" ");
if (this.rows[i][j] == -1) {
stringBuffer.append("B");
} else if (this.rows[i][j] == 0) {
stringBuffer.append(" ");
} else if (this.rows[i][j] == 1) {
stringBuffer.append("R");
} else {
//this case should never happen. If we reach this, 
// something went logically wrong!
//stringBuffer.append(rows[i][j]);
}
}
stringBuffer.append(" |");
}
stringBuffer.append("\n");
return stringBuffer.toString();
}

@Override
public String toString() {
return this.toString("");
}

@Override
public boolean validMove(int[] gamePress, int[] gameRelease,
int[] gameClick, int currentPlayer) {
return validNode(gameClick[1], gameClick[0], currentPlayer, true);
}

@Override
public GameModel updateGame(int[] gamePress, int[] gameRelease, int[] gameClick, int currentPlayer) {
this.rows[gameClick[0]][gameClick[1]] = currentPlayer;
return new Col(this.rows);
}

@Override
public int[] mouseClick(int xPosition, int yPosition, int currentPlayer) {
int[] xBounds = new int[100];
int[] yBounds = new int[100];
int[] indexArray = new int[2];

// Check if the click was inside the rectangle area.
for (int i = 0; i < this.rows.length; i++) {
System.out.println("Col" + xPosition + "," + yPosition);
for (int j = 0; j < this.rows[i].length; j++) {
xBounds[j] = j * 30 + 48;
yBounds[i] = i * 35 + 47;
xBounds[j] && xPosition if ((xPosition > xBounds[j] && xPosition < xBounds[j] + 20)
 yBounds[i]" && yPosition > yBounds[i]
&& yPosition < yBounds[i] + 20) {

indexArray[0] = (int) (Math.floor((yPosition - 47) / 35));
indexArray[1] = (int) (Math.floor((xPosition - 48) / 30));
System.out.println(indexArray[0] + "," + indexArray[1]);
return indexArray;
}
}
}
indexArray[0] = -1;
indexArray[1] = -1;
return indexArray;


}

@Override
public int[] mousePressedHandler(int xPosition, int yPosition) {
return null;
}

@Override
public int[] mouseRelease(int xPosition, int yPosition) {
return null;
}

@Override
public String[] getInstructions(int currentPlayer) {
String[] instructions = new String[3];
if (currentPlayer == 1) {
instructions[2] = "BLUE";
} else {
instructions[2] = "RED";
}
instructions[0] = "Welcome to Col! ";
instructions[1] = "It's now " + instructions[2] + "'s turn. Click on an empty circle to claim it. You may not claim a circle adjacent to a circle you've already claimed on the same row.";

return instructions;
}
}
